/***************************************************************************
 *   Copyright (C) 2009 by Docteur Pierre-Marie Desombre.   *
 *   pm.desombre@medsyn.fr  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 3 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "bmi.h"
#include "courbe.h"
#include "common/settings.h"
//#include "common/log.h"
#include "common/constants.h"
#include "common/textparser.h"
#include <QtGui>
#include <QtCore>
using namespace Constants;
enum Warn{WarnDebug = true};

bmi::bmi(QStandardItemModel* model):m_model(0), m_obesity(false)
{
    m_model = model;
}


bmi::~bmi(){}

void bmi::calc()
{
      Curses *cf = new Curses(m_model);
      cf -> show();
}

/*void bmi::lissage(QMultiMap<int,QString> & multiMap)
{

    QString value;
    QStringList listOfNonEmptyValues;

    QMapIterator<int,QString> itMap(multiMap);
    while(itMap.hasNext()){
        itMap.next();
        listOfNonEmptyValues << itMap.value();
        qDebug() << __FILE__ << " " << QString::number(__LINE__) << " " << itMap.value();
    }
    //qDebug() << __FILE__ << " " << QString::number(__LINE__) ;

    QString beginningValue;
    if(listOfNonEmptyValues[0] != "zero"){
        beginningValue = listOfNonEmptyValues[0];
        }
    else{
        int it = 0;
        while(listOfNonEmptyValues[it] == "zero"){
            beginningValue = listOfNonEmptyValues[it+1];
            it++;
        }
    }

    qDebug() << __FILE__ << " " << QString::number(__LINE__) << " beginningValue = " << beginningValue;
    qDebug() << __FILE__ << " " << QString::number(__LINE__) << " m_AgeCalc = " << QString::number(m_AgeCalc);
    //listOfNonEmptyValues.removeAll("");
    qDebug() << __FILE__ << " " << QString::number(__LINE__) << " multiMap.size() = " << multiMap.size();
    if(m_AgeCalc > 21){
        qDebug() << __FILE__ << " " << QString::number(__LINE__) << "sup 21" ;
        QMapIterator<int,QString> itNew(multiMap);
        itNew.toFront();
        while(itNew.hasNext()){
            itNew.next();
            if (itNew.value() == "zero" )
            {qDebug() << __FILE__ << QString::number(__LINE__) << " key =" << QString::number(itNew.key()) ;
            	  if (itNew.key() == 1)
            	  {qDebug() << __FILE__ << QString::number(__LINE__) << " has previous ="  ;
            	  	  value = beginningValue;
            	  	  
            	      }
    	  else{   itNew.previous();
    	          int previousKey = itNew.previous().key();
    	          qDebug() << __FILE__ << QString::number(__LINE__) << " previousKey =" << QString::number(previousKey) ;
            	          value = multiMap.value(previousKey);
            	          qDebug() << __FILE__ << QString::number(__LINE__) << " value =" << value ;
            	          itNew.next();
            	          itNew.next();
          
            	      }
            	  //qDebug() << __FILE__ << QString::number(__LINE__) << " itNew.key =" << QString::number(itNew.key()) ;
            	  //qDebug() << __FILE__ << QString::number(__LINE__) << " value =" << value ;
            	  multiMap.replace(itNew.key(),value);
                }
            }
         }
    else{
        //qDebug() << __FILE__ << " " << QString::number(__LINE__) ;
        for(int i = 1 ; i < multiMap.size()+1  ; i ++){
           if(multiMap.value(i) == "zero" ){
               double valueBefore = multiMap.value(i-1).toDouble();
               if(i == 1){
                    value = beginningValue;
                    qDebug() << __FILE__ << QString::number(__LINE__) << " beginningvalue = " << value;
                    multiMap.replace(i,value);
                }
               if(i>1 && i< multiMap.size()){

                    double valueEvaluateAfter = 0.00;
                    int j = i;
                    qDebug() << __FILE__ << QString::number(__LINE__) << " j = " << QString::number(j);
                    int k = j+1;
                    while(m_hashD.contains(j+2) && m_hashD.value(j+1) == "zero" ){
                        k = j+1;
                        j++;
                        }
                        qDebug() << __FILE__ << QString::number(__LINE__) << " k = " << QString::number(k);
                     if(multiMap.value(k) != "zero"){
                         valueEvaluateAfter =   multiMap.value(k).toDouble();
                         qDebug() << __FILE__ << QString::number(__LINE__) << " valueEvaluateAfter = " << QString::number(valueEvaluateAfter);
                     }
                     else{
                         valueEvaluateAfter = valueBefore;
                         qDebug() << __FILE__ << QString::number(__LINE__) << " valueEvaluateAfter = " << QString::number(valueEvaluateAfter);
                         }
                         qDebug() << __FILE__ << QString::number(__LINE__) << " valueBefore = " << QString::number(valueBefore);
                         qDebug() << __FILE__ << QString::number(__LINE__) << " valueEvaluateAfter = " << QString::number(valueEvaluateAfter);
                    value = QString::number((valueBefore +  valueEvaluateAfter )/2);
                    multiMap.replace(i,value);
                }
                if(i == multiMap.size()){
                    double valueBeforeBefore = 0.00;
                    if(i> 2){
                        valueBeforeBefore = multiMap.value(i-2).toDouble();
                        }
                    else{
                        valueBeforeBefore = multiMap.value(i-1).toDouble();
                        }
                    value = QString::number((valueBefore +  valueBeforeBefore )/2);
                    multiMap.replace(i,value);

                    }
           }
        }
    }
}*/

void bmi::test(){
    settings setting;
    QString variation = QString::number(setting.value(BMI_VARIATION).toDouble()*100);
    textParser parsedText;
    QHash<QString,QString> hashTexts = parsedText.readTextFile();
    QString title = trUtf8("Information");
    QString text = trUtf8("Il n'y a pas de problème.");
    QString informativeText = trUtf8("Tout baigne.");
    if(m_AgeCalc < 6 && bmiOneToFiveOverVariation()){
        if(m_obesity == false){
            title = hashTexts.value("titleChildBeforeSix");
            text =  hashTexts.value("textChildBeforeSix")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextChildNoObBeforeSix");
                                 }
        if(m_obesity == true){
            title = hashTexts.value("titleChildBeforeSix");
            text =  hashTexts.value("textChildBeforeSix")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextChildObeseBeforeSix");
        }
        if(isItAnAbnormalHeightVariation() == true){
            title = hashTexts.value("titleChildBeforeSix");
            text =  hashTexts.value("textChildBeforeSix")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextSyndromicObesity");
        }

    }
    else if (m_AgeCalc > 5 && m_AgeCalc < 22 && bmiChildSixToTwentyOneOverVariation()){
        title = hashTexts.value("titleChildAfterSix");
        text = hashTexts.value("textChildAfterSix")+" "+variation+" %";
        if(m_obesity == false){
            informativeText = hashTexts.value("informativeTextChildNonOverweightAfterSix");
            }
        if(m_obesity == true){
            informativeText = hashTexts.value("informativeTextChildOverweightAfterSix");
            }
        if(isItAnAbnormalHeightVariation() == true){
            title = hashTexts.value("titleChildAfterSix");
            text =  hashTexts.value("textChildAfterSix")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextSyndromicObesity");
        }
    }
    else if(m_AgeCalc > 21 && bmiAdultOverVariation()){
        if(m_obesity == false){
            title = hashTexts.value("titleAdult");
            text =  hashTexts.value("textAdult")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextAdult");
            qDebug() << __FILE__ << QString::number(__LINE__) << " title =  " << title;
                                 }
        if(m_obesity == true){
            title = hashTexts.value("titleAdult");
            text =  hashTexts.value("textAdult")+" "+variation+" %";
            informativeText = hashTexts.value("informativeTextObeseAdult");
            qDebug() << __FILE__ << QString::number(__LINE__) << " title =  " << title;
        }

    }
    myMessage(title,text,informativeText);

}

bool bmi::bmiOneToFiveOverVariation(){
  bool ret = false;
  /*settings set;
  double minVariation = set.value(BMI_VARIATION).toDouble();  
  QList<int> listOfKeys = m_hashW.keys();
  double lastW = m_hashW.value(listOfKeys.last()).toDouble();
  double lastH = m_hashH.value(listOfKeys.last()).toDouble();
  listOfKeys.removeLast();
  double beforeLastW = m_hashW.value(listOfKeys.last()).toDouble();
  double beforeLastH = m_hashH.value(listOfKeys.last()).toDouble();
  double lastBmi = (lastW*10000)/(lastH*lastH);
  double beforeLastBmi = (beforeLastW*10000)/(beforeLastH*beforeLastH);
  double lastBmiRef = m_maxAbaqueHash.value(m_AgeCalc).toDouble();
  //calcul date before
  QDate dateBefore = QDate::fromString(m_hashD.value(listOfKeys.last()),"yyyy-MM-dd");
  int ageBefore = ageCalculated(dateBefore);
  double BeforeLastBmiRef = m_maxAbaqueHash.value(ageBefore).toDouble();
  double difOfBmi = lastBmi - lastBmiRef;
  double difOfBeforeBmi = beforeLastBmi - BeforeLastBmiRef;
  double bmiLittleChildVariation = 0.00;

  if(difOfBmi == 0.00 && difOfBeforeBmi == 0.00){
      m_obesity = true;
      bmiLittleChildVariation = 0.00;
      ret = true;
  }
  else if(difOfBmi > 0.00 && difOfBeforeBmi > 0.00){
      if(difOfBmi > difOfBeforeBmi){
          bmiLittleChildVariation = 1 - (difOfBeforeBmi/difOfBmi);
          qDebug() << __FILE__ << " " << QString::number(__LINE__)
                   << " bmiLittleChildVariation = "<< bmiLittleChildVariation;
      }
      else if(difOfBmi < difOfBeforeBmi){
          bmiLittleChildVariation = (difOfBmi/difOfBeforeBmi) -1;
          qDebug() << __FILE__ << " " << QString::number(__LINE__)
                   << " bmiLittleChildVariation = "<< bmiLittleChildVariation;
      }
      if(bmiLittleChildVariation > minVariation){
          m_obesity = true;
          ret = true;
      }
  }
  else if(difOfBmi > 0.00 && difOfBeforeBmi < 0.00){
      bmiLittleChildVariation =  1 - (lastBmi/beforeLastBmi);
      qDebug() << __FILE__ << " " << QString::number(__LINE__)
                   << " bmiLittleChildVariation = "<< bmiLittleChildVariation;
      if(bmiLittleChildVariation > minVariation){
          m_obesity = true;
          ret = true;
      }
  }
  else if(difOfBmi < 0.00 && difOfBeforeBmi > 0.00){
      bmiLittleChildVariation = (beforeLastBmi/lastBmi) - 1;
      qDebug() << __FILE__ << " " << QString::number(__LINE__)
               << " bmiLittleChildVariation = "<< bmiLittleChildVariation;
      m_obesity = false;
      ret = false;
  }
  else if(difOfBmi < 0.00 && difOfBeforeBmi < 0.00){
      bmiLittleChildVariation = 1 - (difOfBmi/difOfBeforeBmi);
      qDebug() << __FILE__ << " " << QString::number(__LINE__)
               << " bmiLittleChildVariation = "<< bmiLittleChildVariation;
      m_obesity = false;
      if(bmiLittleChildVariation == 0){
          ret = false;
      }
      else if(bmiLittleChildVariation < 0 || bmiLittleChildVariation < minVariation ){
          ret = false;
      }
      else{
          ret = true;
      }
  }*/
  return ret;
}

bool bmi::bmiAdultOverVariation(){
  bool retAdult = false;
  /*settings set;
  double minVariation = set.value(BMI_VARIATION).toDouble();

  qDebug() << __FILE__ << QString::number(__LINE__) << " minVariation =  " << QString::number(minVariation);
  QList<int> listOfKeys = m_hashW.keys();

  double lastW = m_hashW.value(listOfKeys.last()).toDouble();
  qDebug() << __FILE__ << QString::number(__LINE__) << " lastW =  " << QString::number(lastW);
  double lastH = m_hashH.value(listOfKeys.last()).toDouble();
  qDebug() << __FILE__ << QString::number(__LINE__) << " lastH =  " << QString::number(lastH);
  listOfKeys.removeLast();
  double beforeLastW = m_hashW.value(listOfKeys.last()).toDouble();
  qDebug() << __FILE__ << QString::number(__LINE__) << " beforeLastW =  " << QString::number(beforeLastW);
  double beforeLastH = m_hashH.value(listOfKeys.last()).toDouble();
  qDebug() << __FILE__ << QString::number(__LINE__) << " beforeLastH =  " << QString::number(beforeLastH);
  double lastBmi = (lastW*10000)/(lastH*lastH);
  qDebug() << __FILE__ << QString::number(__LINE__) << " lastBmi =  " << QString::number(lastBmi);
  double beforeLastBmi = (beforeLastW*10000)/(beforeLastH*beforeLastH);
  qDebug() << __FILE__ << QString::number(__LINE__) << " beforeLastBmi =  " << QString::number(beforeLastBmi);
  double difOfBmi = lastBmi - beforeLastBmi;
  qDebug() << __FILE__ << QString::number(__LINE__) << " difOfBmi =  " << QString::number(difOfBmi);
  if(difOfBmi > minVariation*beforeLastBmi){
      retAdult = true;
  }
  if(lastBmi > 30){
      m_obesity = true;
  }*/
  return retAdult;
}

void bmi::fillMaximumAbaqueHash(QString & sexe){
  settings setAb;
  QString file;
  QString pathAb = setAb.applicationPath()+"/../resources/abaques";
  if(sexe == "M"){
      file = pathAb+"/abaqueMaxBmiGarcons";
  }
  else if (sexe == "F"){
      file = pathAb+"/abaqueMaxBmiFilles";
  }
  else{
      qWarning() << "It is an hermaphrodite child ? " << __FILE__ << " " << QString::number(__LINE__);
  }
  QFile fileAb(file);
  if(!fileAb.open(QIODevice::ReadOnly)){
      qWarning() << file+" cannot be opened ! " << __FILE__ << " " << QString::number(__LINE__);
  }
  QTextStream streamAb(&fileAb);
  while(!streamAb.atEnd()){
      QString line = streamAb.readLine().replace(" ","").replace("\n","");
      QStringList l = line.split("=");
      int age = l[0].toInt();
      QString taille = l[1];
      m_maxAbaqueHash.insertMulti(age,taille);
  }
}

int bmi::ageCalculated(QDate & date){
  QDate AgeDate       = QDate::fromString(m_dateOfBirth , "yyyy-MM-dd");
  int   AgeCalc           = date.year() - AgeDate.year();

  if(AgeDate.month() - date.month() == 0 && AgeDate.day() - date.day() > 0 ){
      AgeCalc -- ;
  }
  if(AgeDate.month() - date.month() > 0 ){
      AgeCalc -- ;
  }
  return AgeCalc;
}

void bmi::myMessage(QString & title,QString & text,QString & informativeText){
    title.replace("\n","");
    qDebug() << __FILE__ << QString::number(__LINE__) << " title =  " << title;
    QMessageBox mess ;
      //mess.setTextFormat(Qt::PlainText);
      mess.setWindowTitle(title);
      mess.setText(text);
      mess.setInformativeText(informativeText);
      mess.exec();
}

bool bmi::bmiChildSixToTwentyOneOverVariation(){
    bool ret = false;
    /*settings set;
    double minVariation = set.value(BMI_VARIATION).toDouble();
    
    QList<int> listOfKeys = m_hashW.keys();
    double lastW = m_hashW.value(listOfKeys.last()).toDouble();
    double lastH = m_hashH.value(listOfKeys.last()).toDouble();
    listOfKeys.removeLast();
    double beforeLastW = m_hashW.value(listOfKeys.last()).toDouble();
    double beforeLastH = m_hashH.value(listOfKeys.last()).toDouble();
    double lastBmi = (lastW*10000)/(lastH*lastH);
    double beforeLastBmi = (beforeLastW*10000)/(beforeLastH*beforeLastH);
    double lastBmiRef = m_maxAbaqueHash.value(m_AgeCalc).toDouble();
  //calcul date before
    QDate dateBefore = QDate::fromString(m_hashD.value(listOfKeys.last()),"yyyy-MM-dd");
    int ageBefore = ageCalculated(dateBefore);
    double BeforeLastBmiRef = m_maxAbaqueHash.value(ageBefore).toDouble();
    double difOfBmi = lastBmi - lastBmiRef;
    double difOfBeforeBmi = beforeLastBmi - BeforeLastBmiRef;

    if(difOfBeforeBmi < difOfBmi && ((difOfBmi - difOfBeforeBmi) > (minVariation * lastBmi))){
        ret = true;
        if(difOfBmi >= 0 ){
            m_obesity = true;
            }
        }
    if(difOfBeforeBmi == difOfBmi){
         if(difOfBmi >= 0){
            m_obesity = true;
            }
        }*/
    return ret;
}

bool bmi::isItAnAbnormalHeightVariation(){
  bool ret = false;
  /*int key = m_hashD.key(QString::number(m_AgeCalc));
  double heightOfThisDate = m_hashH.value(key).toDouble();
  //moyenne des tailles mesurées  par rapport à tailles
  //1 : construction des tailles moyennes par rapport a age
  QMap<QString,QString> heightMap ;
  settings set;
  QFile file;
  QString fileName;
  if(m_sexe == "M"){
      fileName = "abaqueHeightBoys";
      }
  if(m_sexe == "F"){
      fileName = "abaqueHeightGirls";
      }
  file.setFileName(set.resourcesPath()+"/abaques/"+fileName);
  if(!file.open(QIODevice::ReadOnly)){
      qWarning() << __FILE__ << " " << QString::number(__LINE__) << " "+fileName+" is not found";
  }
  QTextStream stream(&file);
  while(!stream.atEnd()){
      QString line = stream.readLine();
      heightMap.insert(line.split("=")[0].trimmed(),line.split("=")[1].trimmed());
  }
  //2 : calcul des moyennes entre diff
  double sumOfDifOfHeight = 0.00;
  for(int i = 1 ; i < m_hashH.size()+1 ; i++){
      double height = m_hashH.value(i).toDouble();
      QDate thisDate = QDate::fromString(m_hashD.value(i),"yyyy-MM-dd");
      int ageCalc = ageCalculated(thisDate);
      double heightRef = heightMap.value(QString::number(ageCalc)).toDouble();
      sumOfDifOfHeight += height - heightRef;
  }
  double moyenneOfDiffOfHeights = sumOfDifOfHeight/m_hashH.size();
  double heightRefOfThisDate = heightMap.value(QString::number(m_AgeCalc)).toDouble();
  double diffOfHeightsOfThisDate = heightOfThisDate - heightRefOfThisDate; //diff des tailles de ce jour la
  if(diffOfHeightsOfThisDate <= moyenneOfDiffOfHeights){
      ret = true;
  }*/
  return ret;
}

void bmi::createAPointBecauseUniqueValue()
{
    /*QMultiMap<int,QString> m_hashD ;
      QMultiMap<int,QString> m_hashW ;
      QMultiMap<int,QString> m_hashH ;*/
    //date
    /*QDate date = QDate::fromString(m_hashD.values().last(),"yyyy-MM-dd");
    int lastKey = m_hashD.keys().last();
    QDate dateJustAfter = date.addDays(1);
    QString newDate = dateJustAfter.toString("yyyy-MM-dd");
    int newInt = lastKey +1;
    m_hashD.insert(newInt,newDate);
    //weight
    QString weight = m_hashW.values().last();
    m_hashW.insert(newInt,weight);
    //height
    QString height = m_hashH.values().last();
    m_hashH.insert(newInt,height);*/
    
    
}
